package com.zenithmind.library.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zenithmind.common.result.PageResult;
import com.zenithmind.common.result.Result;
import com.zenithmind.common.result.ResultCode;
import com.zenithmind.library.enums.BookStatus;
import com.zenithmind.library.enums.BorrowStatus;
import com.zenithmind.library.mapper.BookCopyMapper;
import com.zenithmind.library.mapper.BookInventoryMapper;
import com.zenithmind.library.mapper.BookMapper;
import com.zenithmind.library.mapper.BorrowRecordMapper;
import com.zenithmind.library.pojo.domain.Book;
import com.zenithmind.library.pojo.domain.BookCopy;
import com.zenithmind.library.pojo.domain.BorrowRecord;
import com.zenithmind.library.pojo.dto.BorrowBookDTO;
import com.zenithmind.library.pojo.dto.RenewBookDTO;
import com.zenithmind.library.pojo.dto.ReturnBookDTO;
import com.zenithmind.library.pojo.query.BorrowRecordQuery;
import com.zenithmind.library.pojo.vo.BorrowRecordVO;
import com.zenithmind.library.pojo.vo.BorrowStatisticsVO;
import com.zenithmind.library.service.BorrowService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 借阅服务实现类
 * 
 * @author ZenithMind
 * @since 2024-06-14
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class BorrowServiceImpl extends ServiceImpl<BorrowRecordMapper, BorrowRecord> implements BorrowService {

    private final BorrowRecordMapper borrowRecordMapper;
    private final BookMapper bookMapper;
    private final BookCopyMapper bookCopyMapper;
    private final BookInventoryMapper bookInventoryMapper;
    private final RedissonClient redissonClient;

    @Value("${library.borrow.max-books-per-user:5}")
    private Integer maxBooksPerUser;

    @Value("${library.borrow.default-borrow-days:30}")
    private Integer defaultBorrowDays;

    @Value("${library.borrow.max-borrow-days:90}")
    private Integer maxBorrowDays;

    @Value("${library.borrow.renewal-times:2}")
    private Integer maxRenewalTimes;

    @Value("${library.borrow.overdue-fine-per-day:1.0}")
    private Double overdueFinePerDay;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<BorrowRecordVO> borrowBook(BorrowBookDTO borrowDTO) {
        log.info("借阅图书，数据：{}", borrowDTO);

        String lockKey = "borrow:book:" + borrowDTO.getBookId() + ":" + borrowDTO.getUserId();
        RLock lock = redissonClient.getLock(lockKey);

        try {
            // 获取分布式锁，防止并发借阅
            if (!lock.tryLock(10, 30, TimeUnit.SECONDS)) {
                return Result.fail(ResultCode.FAIL.getCode(), "系统繁忙，请稍后重试", null);
            }

            // 检查用户是否可以借阅
            Result<Boolean> canBorrowResult = canUserBorrow(borrowDTO.getUserId(), borrowDTO.getBookId());
            if (!canBorrowResult.isSuccess()) {
                return Result.fail(canBorrowResult.getCode(), canBorrowResult.getMsg(), null);
            }

            // 检查图书是否可以借阅
            Result<Boolean> canBookBeBorrowedResult = canBookBeBorrowed(borrowDTO.getBookId());
            if (!canBookBeBorrowedResult.isSuccess()) {
                return Result.fail(canBookBeBorrowedResult.getCode(), canBookBeBorrowedResult.getMsg(), null);
            }

            // 查找可用的图书副本
            BookCopy availableCopy = findAvailableBookCopy(borrowDTO.getBookId(), borrowDTO.getBookCopyId());
            if (availableCopy == null) {
                return Result.fail(ResultCode.NOT_FOUND.getCode(), "没有可借阅的图书副本", null);
            }

            // 创建借阅记录
            BorrowRecord borrowRecord = createBorrowRecord(borrowDTO, availableCopy);
            boolean saved = save(borrowRecord);
            if (!saved) {
                return Result.fail(ResultCode.FAIL.getCode(), "创建借阅记录失败", null);
            }

            // 更新图书副本状态
            updateBookCopyStatus(availableCopy.getId(), BookStatus.BORROWED, borrowDTO.getUserId());

            // 更新图书库存和借阅次数
            updateBookStockAndCount(borrowDTO.getBookId());

            // 转换为VO并返回
            BorrowRecordVO borrowRecordVO = convertToVO(borrowRecord);
            return Result.success(borrowRecordVO);

        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return Result.fail(ResultCode.INTERNAL_SERVER_ERROR.getCode(), "系统异常，请稍后重试", null);
        } catch (Exception e) {
            log.error("借阅图书失败", e);
            return Result.fail(ResultCode.FAIL.getCode(), "借阅失败：" + e.getMessage(), null);
        } finally {
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<BorrowRecordVO> returnBook(ReturnBookDTO returnDTO) {
        log.info("归还图书，数据：{}", returnDTO);

        // 查询借阅记录
        BorrowRecord borrowRecord = getById(returnDTO.getBorrowRecordId());
        if (borrowRecord == null) {
            return Result.fail(ResultCode.NOT_FOUND.getCode(), "借阅记录不存在", null);
        }

        // 检查借阅状态
        if (borrowRecord.getStatus() == null || borrowRecord.getStatus() == 1) {
            return Result.fail(ResultCode.PRECONDITION_FAILED.getCode(), "该图书已归还", null);
        }

        // 更新借阅记录
        LocalDate returnDate = returnDTO.getReturnDate() != null ? 
            returnDTO.getReturnDate() : LocalDate.now();
        
        borrowRecord.setReturnDate(returnDate);
        borrowRecord.setStatus(BorrowStatus.RETURNED.getCode());
        borrowRecord.setReturnOperatorId(returnDTO.getOperatorId());
        borrowRecord.setReturnRemarks(returnDTO.getReturnRemarks());
        borrowRecord.setUpdateTime(LocalDateTime.now());

        // 计算逾期天数和罚金
        if (returnDate.isAfter(borrowRecord.getDueDate())) {
            int overdueDays = (int) java.time.temporal.ChronoUnit.DAYS.between(
                borrowRecord.getDueDate(), returnDate);
            double fineAmount = overdueDays * overdueFinePerDay;
            
            borrowRecord.setOverdueDays(overdueDays);
            borrowRecord.setFineAmount(java.math.BigDecimal.valueOf(fineAmount));
        }

        boolean updated = updateById(borrowRecord);
        if (!updated) {
            return Result.fail(ResultCode.FAIL.getCode(), "更新借阅记录失败", null);
        }

        // 更新图书副本状态
        updateBookCopyStatus(borrowRecord.getBookCopyId(), BookStatus.AVAILABLE, null);

        // 更新图书库存
        bookMapper.incrementAvailableCopies(borrowRecord.getBookId());
        bookMapper.decrementBorrowedCopies(borrowRecord.getBookId());

        // 转换为VO并返回
        BorrowRecordVO borrowRecordVO = convertToVO(borrowRecord);
        return Result.success(borrowRecordVO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<BorrowRecordVO> renewBook(RenewBookDTO renewDTO) {
        log.info("续借图书，数据：{}", renewDTO);

        // 查询借阅记录
        BorrowRecord borrowRecord = getById(renewDTO.getBorrowRecordId());
        if (borrowRecord == null) {
            return Result.fail(ResultCode.NOT_FOUND.getCode(), "借阅记录不存在", null);
        }

        // 检查是否可以续借
        if (!canRenewBook(borrowRecord)) {
            return Result.fail(ResultCode.PRECONDITION_FAILED.getCode(), "该图书不能续借", null);
        }

        // 计算新的到期日期
        LocalDate newDueDate = renewDTO.getNewDueDate();
        if (newDueDate == null) {
            int renewDays = renewDTO.getRenewDays() != null ? 
                renewDTO.getRenewDays() : defaultBorrowDays;
            newDueDate = borrowRecord.getDueDate().plusDays(renewDays);
        }

        // 更新借阅记录
        borrowRecord.setDueDate(newDueDate);
        borrowRecord.setRenewalCount(borrowRecord.getRenewalCount() + 1);
        borrowRecord.setStatus(BorrowStatus.RENEWED.getCode());
        borrowRecord.setUpdateTime(LocalDateTime.now());

        boolean updated = updateById(borrowRecord);
        if (!updated) {
            return Result.fail(ResultCode.FAIL.getCode(), "续借失败", null);
        }

        // 转换为VO并返回
        BorrowRecordVO borrowRecordVO = convertToVO(borrowRecord);
        return Result.success(borrowRecordVO);
    }

    @Override
    public PageResult<BorrowRecordVO> getBorrowRecordPage(BorrowRecordQuery query) {
        log.info("分页查询借阅记录，查询条件：{}", query);

        Page<BorrowRecordVO> page = query.toPage();
        IPage<BorrowRecordVO> result = borrowRecordMapper.selectBorrowRecordPage(page, query);

        return PageResult.of(result.getRecords(), result.getTotal(), result.getCurrent(), result.getSize());
    }

    @Override
    public PageResult<BorrowRecordVO> getBorrowRecordsByUser(String userId, BorrowRecordQuery query) {
        log.info("根据用户查询借阅记录，用户ID：{}，查询条件：{}", userId, query);

        Page<BorrowRecordVO> page = query.toPage();
        IPage<BorrowRecordVO> result = borrowRecordMapper.selectBorrowRecordsByUser(page, userId, query);

        return PageResult.of(result.getRecords(), result.getTotal(), result.getCurrent(), result.getSize());
    }

    @Override
    public PageResult<BorrowRecordVO> getBorrowRecordsByBook(String bookId, BorrowRecordQuery query) {
        log.info("根据图书查询借阅记录，图书ID：{}，查询条件：{}", bookId, query);

        Page<BorrowRecordVO> page = query.toPage();
        IPage<BorrowRecordVO> result = borrowRecordMapper.selectBorrowRecordsByBook(page, bookId, query);

        return PageResult.of(result.getRecords(), result.getTotal(), result.getCurrent(), result.getSize());
    }

    @Override
    public List<BorrowRecordVO> getCurrentBorrowsByUser(String userId) {
        log.info("获取用户当前借阅的图书，用户ID：{}", userId);
        return borrowRecordMapper.selectCurrentBorrowsByUser(userId);
    }

    @Override
    public PageResult<BorrowRecordVO> getOverdueBorrows(BorrowRecordQuery query) {
        log.info("获取逾期借阅记录，查询条件：{}", query);

        Page<BorrowRecordVO> page = query.toPage();
        IPage<BorrowRecordVO> result = borrowRecordMapper.selectOverdueBorrows(page, query);

        return PageResult.of(result.getRecords(), result.getTotal(), result.getCurrent(), result.getSize());
    }

    @Override
    public PageResult<BorrowRecordVO> getDueSoonBorrows(Integer days, BorrowRecordQuery query) {
        log.info("获取即将到期的借阅记录，天数：{}，查询条件：{}", days, query);

        Page<BorrowRecordVO> page = query.toPage();
        IPage<BorrowRecordVO> result = borrowRecordMapper.selectDueSoonBorrows(page, days, query);

        return PageResult.of(result.getRecords(), result.getTotal(), result.getCurrent(), result.getSize());
    }

    @Override
    public Result<Boolean> canUserBorrow(String userId, String bookId) {
        // 检查用户当前借阅数量
        int currentBorrows = borrowRecordMapper.countUserCurrentBorrows(userId);
        if (currentBorrows >= maxBooksPerUser) {
            return Result.fail(ResultCode.PRECONDITION_FAILED.getCode(), "借阅数量已达上限（" + maxBooksPerUser + "本）", null);
        }

        // 检查用户是否已借阅该图书
        int userBookBorrows = borrowRecordMapper.countUserCurrentBorrowByBook(userId, bookId);
        if (userBookBorrows > 0) {
            return Result.fail(ResultCode.CONFLICT.getCode(), "您已借阅该图书", null);
        }

        // 检查用户是否有逾期记录
        int overdueRecords = borrowRecordMapper.countUserOverdueRecords(userId);
        if (overdueRecords > 0) {
            return Result.fail(ResultCode.PRECONDITION_FAILED.getCode(), "您有逾期未还的图书，请先归还", null);
        }

        // 检查用户是否有未支付的罚金
        Double unpaidFines = borrowRecordMapper.sumUserUnpaidFines(userId);
        if (unpaidFines != null && unpaidFines > 0) {
            return Result.fail(ResultCode.PRECONDITION_FAILED.getCode(), "您有未支付的罚金，请先支付", null);
        }

        return Result.success(true);
    }

    @Override
    public Result<Boolean> canBookBeBorrowed(String bookId) {
        Book book = bookMapper.selectById(bookId);
        if (book == null) {
            return Result.fail(ResultCode.NOT_FOUND.getCode(), "图书不存在", null);
        }

        if (book.getStatus() == null || book.getStatus() != 1) {
            return Result.fail(ResultCode.PRECONDITION_FAILED.getCode(), "图书已下架", null);
        }

        // 检查图书库存
        try {
            Boolean sufficient = bookInventoryMapper.isStockSufficient(book.getId(), 1);
            if (sufficient == null || !sufficient) {
                return Result.fail(ResultCode.PRECONDITION_FAILED.getCode(), "图书库存不足", null);
            }
        } catch (Exception e) {
            log.error("检查图书库存失败，图书ID：{}", book.getId(), e);
            return Result.fail(ResultCode.INTERNAL_SERVER_ERROR.getCode(), "检查图书库存失败", null);
        }

        return Result.success(true);
    }

    @Override
    public Result<Double> calculateFine(String borrowRecordId) {
        BorrowRecord borrowRecord = getById(borrowRecordId);
        if (borrowRecord == null) {
            return Result.fail(ResultCode.NOT_FOUND.getCode(), "借阅记录不存在", null);
        }

        if (borrowRecord.getReturnDate() != null) {
            return Result.success(borrowRecord.getFineAmount().doubleValue());
        }

        LocalDate dueDate = borrowRecord.getDueDate();
        LocalDate currentDate = LocalDate.now();
        
        if (currentDate.isAfter(dueDate)) {
            int overdueDays = (int) java.time.temporal.ChronoUnit.DAYS.between(dueDate, currentDate);
            double fineAmount = overdueDays * overdueFinePerDay;
            return Result.success(fineAmount);
        }

        return Result.success(0.0);
    }

    @Override
    public Result<Void> payFine(String borrowRecordId, Double amount) {
        log.info("支付罚金，借阅记录ID：{}，金额：{}", borrowRecordId, amount);

        if (borrowRecordId == null || borrowRecordId.trim().isEmpty()) {
            return Result.fail(ResultCode.PARAM_ERROR.getCode(), "借阅记录ID不能为空", null);
        }

        if (amount == null || amount <= 0) {
            return Result.fail(ResultCode.PARAM_ERROR.getCode(), "支付金额必须大于0", null);
        }

        try {
            // 获取借阅记录
            BorrowRecord borrowRecord = getById(borrowRecordId);
            if (borrowRecord == null) {
                return Result.fail(ResultCode.NOT_FOUND.getCode(), "借阅记录不存在", null);
            }

            // 检查是否需要支付罚金
            if (borrowRecord.getFineAmount() == null || borrowRecord.getFineAmount().compareTo(BigDecimal.ZERO) <= 0) {
                return Result.fail(ResultCode.PRECONDITION_FAILED.getCode(), "该借阅记录无需支付罚金", null);
            }

            // 检查支付金额是否正确
            BigDecimal payAmount = BigDecimal.valueOf(amount);
            if (payAmount.compareTo(borrowRecord.getFineAmount()) != 0) {
                return Result.fail(ResultCode.PARAM_ERROR.getCode(),
                    String.format("支付金额不正确，应支付：%.2f元", borrowRecord.getFineAmount()), null);
            }

            // 更新借阅记录的罚金状态
            borrowRecord.setFinePaid(1); // 1表示已支付
            // 注意：如果BorrowRecord没有finePayTime字段，这里可以使用updateTime记录支付时间
            updateById(borrowRecord);

            log.info("罚金支付成功，借阅记录ID：{}，金额：{}", borrowRecordId, amount);
            return Result.success();

        } catch (Exception e) {
            log.error("支付罚金失败，借阅记录ID：{}，金额：{}", borrowRecordId, amount, e);
            return Result.fail(ResultCode.INTERNAL_SERVER_ERROR.getCode(), "支付罚金失败", null);
        }
    }

    @Override
    public Result<Void> sendDueReminder(String borrowRecordId) {
        log.info("发送到期提醒，借阅记录ID：{}", borrowRecordId);

        if (borrowRecordId == null || borrowRecordId.trim().isEmpty()) {
            return Result.fail(ResultCode.PARAM_ERROR.getCode(), "借阅记录ID不能为空", null);
        }

        try {
            // 获取借阅记录
            BorrowRecord borrowRecord = getById(borrowRecordId);
            if (borrowRecord == null) {
                return Result.fail(ResultCode.NOT_FOUND.getCode(), "借阅记录不存在", null);
            }

            // 检查是否已归还
            if (borrowRecord.getReturnDate() != null) {
                return Result.fail(ResultCode.PRECONDITION_FAILED.getCode(), "图书已归还，无需提醒", null);
            }

            // 检查是否即将到期或已逾期
            LocalDate dueDate = borrowRecord.getDueDate();
            LocalDate today = LocalDate.now();

            if (dueDate.isAfter(today.plusDays(7))) {
                return Result.fail(ResultCode.PRECONDITION_FAILED.getCode(), "距离到期时间超过7天，暂不发送提醒", null);
            }

            // 实际项目中，这里应该：
            // 1. 获取用户信息（手机号、邮箱等）
            // 2. 调用短信/邮件服务发送提醒
            // 3. 记录提醒发送日志

            // 模拟发送提醒
            String reminderMessage;
            if (dueDate.isBefore(today)) {
                long overdueDays = today.toEpochDay() - dueDate.toEpochDay();
                reminderMessage = String.format("您借阅的图书已逾期%d天，请尽快归还", overdueDays);
            } else if (dueDate.isEqual(today)) {
                reminderMessage = "您借阅的图书今日到期，请及时归还";
            } else {
                long remainingDays = dueDate.toEpochDay() - today.toEpochDay();
                reminderMessage = String.format("您借阅的图书将在%d天后到期，请注意归还时间", remainingDays);
            }

            log.info("发送到期提醒成功，借阅记录ID：{}，提醒内容：{}", borrowRecordId, reminderMessage);
            return Result.success();

        } catch (Exception e) {
            log.error("发送到期提醒失败，借阅记录ID：{}", borrowRecordId, e);
            return Result.fail(ResultCode.INTERNAL_SERVER_ERROR.getCode(), "发送到期提醒失败", null);
        }
    }

    @Override
    public Result<Integer> batchSendDueReminders(Integer days) {
        log.info("批量发送到期提醒，提前天数：{}", days);

        if (days == null || days < 0) {
            days = 3; // 默认提前3天提醒
        }

        try {
            // 查询需要提醒的借阅记录
            LocalDate reminderDate = LocalDate.now().plusDays(days);

            LambdaQueryWrapper<BorrowRecord> wrapper = new LambdaQueryWrapper<>();
            wrapper.isNull(BorrowRecord::getReturnDate) // 未归还
                   .le(BorrowRecord::getDueDate, reminderDate) // 到期日期在提醒范围内
                   .eq(BorrowRecord::getStatus, 1); // 借阅中状态

            List<BorrowRecord> borrowRecords = list(wrapper);

            if (borrowRecords.isEmpty()) {
                log.info("没有需要发送提醒的借阅记录");
                return Result.success(0);
            }

            int successCount = 0;
            int failCount = 0;

            for (BorrowRecord borrowRecord : borrowRecords) {
                try {
                    Result<Void> reminderResult = sendDueReminder(borrowRecord.getId());
                    if (reminderResult.isSuccess()) {
                        successCount++;
                    } else {
                        failCount++;
                        log.warn("发送提醒失败，借阅记录ID：{}，原因：{}",
                            borrowRecord.getId(), reminderResult.getMsg());
                    }
                } catch (Exception e) {
                    failCount++;
                    log.error("发送提醒异常，借阅记录ID：{}", borrowRecord.getId(), e);
                }
            }

            log.info("批量发送到期提醒完成，总数：{}，成功：{}，失败：{}",
                borrowRecords.size(), successCount, failCount);

            return Result.success(successCount);

        } catch (Exception e) {
            log.error("批量发送到期提醒失败", e);
            return Result.fail(ResultCode.INTERNAL_SERVER_ERROR.getCode(), "批量发送到期提醒失败", null);
        }
    }

    @Override
    public BorrowStatisticsVO getBorrowStatistics(LocalDate startDate, LocalDate endDate) {
        return borrowRecordMapper.selectBorrowStatistics(startDate, endDate);
    }

    @Override
    public BorrowStatisticsVO getUserBorrowStatistics(String userId, LocalDate startDate, LocalDate endDate) {
        return borrowRecordMapper.selectUserBorrowStatistics(userId, startDate, endDate);
    }

    @Override
    public BorrowStatisticsVO getBookBorrowStatistics(String bookId, LocalDate startDate, LocalDate endDate) {
        return borrowRecordMapper.selectBookBorrowStatistics(bookId, startDate, endDate);
    }

    @Override
    public Result<String> exportBorrowRecords(BorrowRecordQuery query) {
        log.info("导出借阅记录，查询条件：{}", query);

        try {
            // 1. 查询数据
            if (query == null) {
                query = new BorrowRecordQuery();
            }

            // 设置较大的分页大小以获取所有数据
            query.setSize(10000); // 最多导出10000条记录
            PageResult<BorrowRecordVO> pageResult = getBorrowRecordPage(query);

            if (pageResult == null || pageResult.getRecords() == null || pageResult.getRecords().isEmpty()) {
                return Result.fail(ResultCode.NOT_FOUND.getCode(), "没有找到符合条件的借阅记录", null);
            }

            // 2. 生成Excel文件路径
            String timestamp = String.valueOf(System.currentTimeMillis());
            String fileName = "borrow_records_export_" + timestamp + ".xlsx";
            String filePath = "/exports/" + fileName;

            // 3. 这里应该实现实际的Excel生成逻辑
            // 由于没有具体的Excel工具类，这里只是模拟
            log.info("模拟生成Excel文件，包含{}条记录，文件路径：{}", pageResult.getRecords().size(), filePath);

            // 实际项目中，这里应该：
            // - 使用EasyExcel或Apache POI生成Excel文件
            // - 将文件保存到指定目录
            // - 返回文件的访问URL或下载链接

            String resultMessage = String.format("导出成功，共%d条记录，文件：%s",
                pageResult.getRecords().size(), fileName);

            log.info("借阅记录导出完成，记录数：{}，文件：{}", pageResult.getRecords().size(), fileName);
            return Result.success(resultMessage);

        } catch (Exception e) {
            log.error("导出借阅记录失败", e);
            return Result.fail(ResultCode.INTERNAL_SERVER_ERROR.getCode(), "导出失败：" + e.getMessage(), null);
        }
    }

    @Override
    public Result<Integer> autoProcessOverdueRecords() {
        log.info("开始自动处理逾期记录");

        try {
            // 查询所有逾期的借阅记录
            LocalDate today = LocalDate.now();

            LambdaQueryWrapper<BorrowRecord> wrapper = new LambdaQueryWrapper<>();
            wrapper.isNull(BorrowRecord::getReturnDate) // 未归还
                   .lt(BorrowRecord::getDueDate, today) // 已逾期
                   .eq(BorrowRecord::getStatus, 1); // 借阅中状态

            List<BorrowRecord> overdueRecords = list(wrapper);

            if (overdueRecords.isEmpty()) {
                log.info("没有需要处理的逾期记录");
                return Result.success(0);
            }

            int processedCount = 0;

            for (BorrowRecord borrowRecord : overdueRecords) {
                try {
                    // 计算逾期天数
                    long overdueDays = today.toEpochDay() - borrowRecord.getDueDate().toEpochDay();

                    // 更新逾期天数
                    borrowRecord.setOverdueDays((int) overdueDays);

                    // 计算罚金（假设每天罚金0.5元）
                    BigDecimal dailyFine = new BigDecimal("0.50");
                    BigDecimal totalFine = dailyFine.multiply(BigDecimal.valueOf(overdueDays));

                    // 设置罚金金额（如果还没有设置或者需要更新）
                    if (borrowRecord.getFineAmount() == null ||
                        borrowRecord.getFineAmount().compareTo(totalFine) != 0) {
                        borrowRecord.setFineAmount(totalFine);
                    }

                    // 更新借阅记录
                    updateById(borrowRecord);
                    processedCount++;

                    log.debug("处理逾期记录，ID：{}，逾期天数：{}，罚金：{}",
                        borrowRecord.getId(), overdueDays, totalFine);

                } catch (Exception e) {
                    log.error("处理逾期记录失败，借阅记录ID：{}", borrowRecord.getId(), e);
                }
            }

            log.info("自动处理逾期记录完成，总数：{}，处理成功：{}", overdueRecords.size(), processedCount);
            return Result.success(processedCount);

        } catch (Exception e) {
            log.error("自动处理逾期记录失败", e);
            return Result.fail(ResultCode.INTERNAL_SERVER_ERROR.getCode(), "自动处理逾期记录失败", null);
        }
    }

    /**
     * 查找可用的图书副本
     */
    private BookCopy findAvailableBookCopy(String bookId, String bookCopyId) {
        LambdaQueryWrapper<BookCopy> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(BookCopy::getBookId, bookId);
        wrapper.eq(BookCopy::getStatus, BookStatus.AVAILABLE.getCode());
        
        if (StringUtils.hasText(bookCopyId)) {
            wrapper.eq(BookCopy::getId, bookCopyId);
        }
        
        wrapper.last("LIMIT 1");
        return bookCopyMapper.selectOne(wrapper);
    }

    /**
     * 创建借阅记录
     */
    private BorrowRecord createBorrowRecord(BorrowBookDTO borrowDTO, BookCopy bookCopy) {
        BorrowRecord borrowRecord = new BorrowRecord();
        borrowRecord.setUserId(borrowDTO.getUserId());
        borrowRecord.setBookCopyId(bookCopy.getId());
        borrowRecord.setBookId(borrowDTO.getBookId());
        borrowRecord.setBorrowDate(LocalDate.now());
        
        LocalDate dueDate = borrowDTO.getDueDate();
        if (dueDate == null) {
            int borrowDays = borrowDTO.getBorrowDays() != null ? 
                borrowDTO.getBorrowDays() : defaultBorrowDays;
            dueDate = LocalDate.now().plusDays(borrowDays);
        }
        borrowRecord.setDueDate(dueDate);
        
        borrowRecord.setStatus(BorrowStatus.BORROWING.getCode());
        borrowRecord.setRenewalCount(0);
        borrowRecord.setMaxRenewalCount(maxRenewalTimes);
        borrowRecord.setBorrowOperatorId(borrowDTO.getOperatorId());
        borrowRecord.setBorrowRemarks(borrowDTO.getBorrowRemarks());
        borrowRecord.setCreateTime(LocalDateTime.now());
        borrowRecord.setUpdateTime(LocalDateTime.now());
        
        return borrowRecord;
    }

    /**
     * 更新图书副本状态
     */
    private void updateBookCopyStatus(String bookCopyId, BookStatus status, String borrowerId) {
        BookCopy bookCopy = new BookCopy();
        bookCopy.setId(bookCopyId);
        bookCopy.setStatus(status.getCode());
        bookCopy.setCurrentBorrowerId(borrowerId);
        bookCopy.setUpdateTime(LocalDateTime.now());
        
        if (status == BookStatus.BORROWED) {
            bookCopy.setLastBorrowDate(LocalDate.now());
            // 增加借阅次数
            BookCopy existingCopy = bookCopyMapper.selectById(bookCopyId);
            if (existingCopy != null) {
                int borrowCount = existingCopy.getBorrowCount() != null ? 
                    existingCopy.getBorrowCount() + 1 : 1;
                bookCopy.setBorrowCount(borrowCount);
            }
        }
        
        bookCopyMapper.updateById(bookCopy);
    }

    /**
     * 更新图书库存和借阅次数
     */
    private void updateBookStockAndCount(String bookId) {
        bookMapper.decrementAvailableCopies(bookId);
        bookMapper.incrementBorrowedCopies(bookId);
        bookMapper.incrementBorrowCount(bookId);
    }

    /**
     * 检查是否可以续借
     */
    private boolean canRenewBook(BorrowRecord borrowRecord) {
        // 检查借阅状态
        if (borrowRecord.getStatus() == null || 
            (borrowRecord.getStatus() != BorrowStatus.BORROWING.getCode() && 
             borrowRecord.getStatus() != BorrowStatus.RENEWED.getCode())) {
            return false;
        }

        // 检查续借次数
        int renewalCount = borrowRecord.getRenewalCount() != null ? borrowRecord.getRenewalCount() : 0;
        int maxRenewal = borrowRecord.getMaxRenewalCount() != null ? 
            borrowRecord.getMaxRenewalCount() : maxRenewalTimes;
        
        if (renewalCount >= maxRenewal) {
            return false;
        }

        // 检查是否逾期
        return !LocalDate.now().isAfter(borrowRecord.getDueDate());
    }

    /**
     * 转换为VO对象
     */
    private BorrowRecordVO convertToVO(BorrowRecord borrowRecord) {
        BorrowRecordVO vo = new BorrowRecordVO();

        // 复制基本字段
        vo.setId(borrowRecord.getId());
        vo.setUserId(borrowRecord.getUserId());
        vo.setBookCopyId(borrowRecord.getBookCopyId());
        vo.setBookId(borrowRecord.getBookId());
        vo.setBorrowDate(borrowRecord.getBorrowDate());
        vo.setDueDate(borrowRecord.getDueDate());
        vo.setReturnDate(borrowRecord.getReturnDate());
        vo.setStatus(borrowRecord.getStatus());
        vo.setRenewalCount(borrowRecord.getRenewalCount());
        vo.setMaxRenewalCount(borrowRecord.getMaxRenewalCount());
        vo.setOverdueDays(borrowRecord.getOverdueDays());
        vo.setFineAmount(borrowRecord.getFineAmount());
        vo.setFinePaid(borrowRecord.getFinePaid());
        vo.setBorrowRemarks(borrowRecord.getBorrowRemarks());
        vo.setReturnRemarks(borrowRecord.getReturnRemarks());
        vo.setCreateTime(borrowRecord.getCreateTime());
        vo.setUpdateTime(borrowRecord.getUpdateTime());

        // 设置关联数据
        try {
            // 获取图书信息
            if (borrowRecord.getBookId() != null) {
                Book book = bookMapper.selectById(borrowRecord.getBookId());
                if (book != null) {
                    vo.setBookTitle(book.getTitle());
                    vo.setBookIsbn(book.getIsbn());
                    // 注意：Book实体没有直接的author字段，需要通过关联表获取
                    // 这里暂时设置为空，实际项目中需要通过BookAuthor关联表查询
                    vo.setBookAuthor(""); // 待实现作者信息查询
                }
            }

            // 获取图书副本信息
            if (borrowRecord.getBookCopyId() != null) {
                BookCopy bookCopy = bookCopyMapper.selectById(borrowRecord.getBookCopyId());
                if (bookCopy != null) {
                    vo.setBarcode(bookCopy.getBarcode());
                    // 注意：BookCopy可能没有location字段，这里跳过
                }
            }

            // 设置状态描述
            vo.setStatusName(getStatusName(borrowRecord.getStatus()));

            // 注意：BorrowRecordVO已经有isOverdue()方法来判断是否逾期，无需手动设置

        } catch (Exception e) {
            log.warn("获取借阅记录关联数据失败，借阅记录ID：{}", borrowRecord.getId(), e);
        }

        return vo;
    }

    /**
     * 获取状态名称
     */
    private String getStatusName(Integer status) {
        if (status == null) {
            return "未知";
        }

        return switch (status) {
            case 0 -> "预约中";
            case 1 -> "借阅中";
            case 2 -> "已归还";
            case 3 -> "逾期";
            case 4 -> "丢失";
            case 5 -> "损坏";
            default -> "未知状态";
        };
    }
}
